package com.quxing.amazon.config;

import com.quxing.amazon.common.BaseException;
import com.quxing.amazon.common.Result;
import io.lettuce.core.RedisException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Iterator;
import java.util.List;

import static com.quxing.amazon.common.StatusConst.*;


/**
 * @author zhb
 * @description 全局异常处理
 * @date 2020/11/29 14:30
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public Result exception(Exception e) {
        log.error("全局异常信息:{},异常类:{}", e.getMessage(), e.getClass());
        e.printStackTrace();
        return Result.error();
    }

    /**
     * 通用异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(BaseException.class)
    public Result exception(BaseException e) {
        return Result.exception(e);
    }

    /**
     * 请求方法不支持
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public Result exception(HttpRequestMethodNotSupportedException e) {
        log.error("请求方法不支持:{}", e.getMessage());
        return Result.error(HTTP_BAD_METHOD);
    }

    /**
     * 参数不匹配
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public Result exception(ConstraintViolationException e) {
        Iterator<ConstraintViolation<?>> iterator = e.getConstraintViolations().iterator();
        return Result.error(iterator.next().getMessage());
    }

    /**
     * 请求不存在
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = NoHandlerFoundException.class)
    public Result exception(NoHandlerFoundException e) {
        log.error("请求不存在:{}", e.getMessage());
        return Result.error(REQUEST_NOT_FOUND);
    }

    /**
     * redis异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = {RedisException.class})
    public Result exception(RedisException e) {
        log.error("RedisException异常:{}", e.getMessage());
        return Result.error();
    }

    /**
     * redis异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = {RedisConnectionFailureException.class})
    public Result exception(RedisConnectionFailureException e) {
        log.error("RedisConnectionFailureException异常:{}", e.getMessage());
        return Result.error();
    }

    @ExceptionHandler(value = {SQLIntegrityConstraintViolationException.class})
    public Result exception(SQLIntegrityConstraintViolationException e) {
        log.error("数据库异常:{}", e.getMessage());
        return Result.error();
    }

    /**
     * RequestParameter参数不能为空
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public Result exception(MissingServletRequestParameterException e) {
        log.error("RequestParameter参数异常:{}", e.getMessage());
        return Result.error(e.getParameterName() + PARAM_NOT_NULL);
    }

    /**
     * PathVariable参数不匹配
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
    public Result exception(MethodArgumentTypeMismatchException e) {
        log.error("PathVariable参数异常:{}", e.getMessage());
        return Result.error(PARAM_NOT_MATCH);
    }

    /**
     * RequestParameter参数类型不匹配
     *
     * @param e
     * @return
     */
    @ExceptionHandler({BindException.class})
    public Result exception(BindException e) {
        e.printStackTrace();
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        return Result.error(fieldErrors.get(0).getDefaultMessage());
    }

    /**
     * 注解验证参数不匹配
     *
     * @param e
     * @return
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public Result exception(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        return Result.error(fieldErrors.get(0).getDefaultMessage());
    }

    /**
     * 请求体参数异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public Result exception(HttpMessageNotReadableException e) {
        log.error("请求体参数异常:{}", e.getMessage());
        return Result.error(PARAM_NOT_MATCH);
    }
}
